/*
 * Copyright (C) 2015-2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include "PlanetWars2dRT-core/utils/cstring_functions.h"
#include "PlanetWars2dRT-core/utils/arguments_management.h"
#include "PlanetWars2dRT-core/utils/command_line_interface.h"
#include "PlanetWars2dRT-core/utils/color_rgb_const.h"
#include "PlanetWars2dRT-core/specific/compilation_config.h"
#include "PlanetWars2dRT-core/specific/model/planet.h"
#include "PlanetWars2dRT-core/specific/model/universe.h"
#include "PlanetWars2dRT-core/specific/model/universes_hard_coded.h"
#include "PlanetWars2dRT-core/specific/model/game.h"
#include "PlanetWars2dRT-core/specific/controller/game.h"
#include "PlanetWars2dRT-core/specific/controller/player_robots.h"


#define VERSION_MAJOR LIB_PLANET_WARS_2D_RT_CORE_VERSION_MAJOR
#define VERSION_MINOR LIB_PLANET_WARS_2D_RT_CORE_VERSION_MINOR
#define VERSION_MICRO LIB_PLANET_WARS_2D_RT_CORE_VERSION_MICRO


void
help_to_stream_unsafe(FILE* stream,
		      const char* program_command)
{
  fprintf(stream,
	  "Usage: %s",
	  program_command);
  fputc('\n', stream);
}

bool
manage_exit_option(const char* option,
		   const char* program_command)
{
  if (cstring_equals(option, "?")        ||
      cstring_equals(option, "-?")       ||
      cstring_equals(option, "-h")       ||
      cstring_equals(option, "help")     ||
      cstring_equals(option, "--help")   ||
      cstring_equals(option, "--man")    ||
      cstring_equals(option, "manual")   ||
      cstring_equals(option, "--manual") ||
      cstring_equals(option, "info")     ||
      cstring_equals(option, "--info")   ||
      cstring_equals(option, "usage")    ||
      cstring_equals(option, "--usage")  ||
      cstring_equals(option, "--wtf")    ||
      is_a_help_cstring_option_unsafe(option))
    {
      help_to_stream_unsafe(stdout, program_command);
      return true;
    }
  if(cstring_equals(option, "--license") ||
     cstring_equals(option, "--licence") ||
     cstring_equals(option, "--copyright"))
    {
      puts("This program is under "
	   "GNU Affero General Public License 3 "
	   "as published by the Free Software Foundation, "
	   "either version 3 of the License, "
	   "or (at your option) any later version.");
      return true;
    }
  if(cstring_equals(option, "--license-url"))
    {
      puts("https://www.gnu.org/licenses/agpl.html");
      return true;
    }
  if(cstring_equals(option, "--author"))
    {
      puts("The main author of this program is Nicola Spanti, "
	   "also known as RyDroid.");
      return true;
    }
  if(cstring_equals(option, "--auteur"))
    {
      puts("Le créateur et principal contributeur de ce programme est "
	   "Nicola Spanti, aussi connu sous le pseudonyme RyDroid.");
      return true;
    }
  if(cstring_equals(option, "--version"))
    {
      printf("Version %hhu.%hhu.%hhu\n",
	     VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO);
      return true;
    }
  
  return false;
}


int
main(int argc, const char* argv[])
{
  if(argc > 1)
    {
      /* Arguments management with message and exit result */
      if(manage_exit_option(argv[1], argv[0]))
	{
	  return EXIT_SUCCESS;
	}
      
      fprintf(stderr, "Unknow option: %s\n", argv[1]);
      if(argc > 2)
	{
	  fprintf(stderr, "Only one argument is managed.\n");
	}
      return EXIT_FAILURE;
    }
  
  
  /* A game for testing */
  
  game_t a_game;
  game_init_first_time_only_default(&a_game);
  bool success;
  a_game.universe = get_universe_hard_coded_line_3_planets(&success);
  if(!success)
    {
      fprintf(stderr,
	      "At least one error occurred during universe creation!\n");
    }
  
  struct player_t human, robot;
  player_init_first_time_only(&human);
  player_init_first_time_only(&robot);
  if(!player_set_name(&human, "You"))
    {
      fprintf(stderr, "Human player has no name!\n");
    }
  if(!player_set_name(&robot, "Robot"))
    {
      fprintf(stderr, "Robot player has no name!\n");
    }
  human.color = COLOR_RGB_BLUE;
  robot.color = COLOR_RGB_RED;
  human.act = player_robot_stupid_rusher_act;
  robot.act = NULL;
  if(!game_add_player(&a_game, &human))
    {
      fprintf(stderr, "Human player not added!\n");
    }
  if(!game_add_player(&a_game, &robot))
    {
      fprintf(stderr, "Robot player not added!\n");
    }
  
  if(game_is_finished(&a_game))
    {
      fprintf(stderr, "Game is finished!\n");
      const player_t* player = game_get_winner(&a_game);
      fprintf(stderr, "The winner is %s.\n", player->name);
    }
  
  while(game_get_turn(&a_game) < 10000 && !game_is_finished(&a_game))
    {
      game_update_once(&a_game);
      
      printf("## Turn %u\n", game_get_turn(&a_game));
      printf("nb planets %5zu\n", universe_get_nb_planets(&a_game.universe));
      printf("nb ships   %5zu\n", universe_get_nb_ships(&a_game.universe));
      printf("planet0.pi %5u\n",
	     universe_get_const_planet(&a_game.universe, 0)->player_index);
      printf("planet1.pi %5u\n",
	     universe_get_const_planet(&a_game.universe, 1)->player_index);
      printf("planet2.pi %5u\n",
	     universe_get_const_planet(&a_game.universe, 2)->player_index);
      printf("planet2.lf %5u\n",
	     planet_get_life_current(universe_get_const_planet(&a_game.universe, 2)));
    }
  if(game_is_finished(&a_game))
    {
      fprintf(stdout, "Game is finished!\n");
      const player_t* player = game_get_winner(&a_game);
      fprintf(stdout, "The winner is %s.\n", player->name);
    }
  else
    {
      fprintf(stderr, "Game isn't finished!\n");
    }
  
  game_destructor(&a_game);
  
  return EXIT_SUCCESS;
}
